Multithreading has become a mainstream programming technique for improving processing speed by optimizing the shared use of system resources by multiple processes. Multithreading allows the operating system to manage the use of a software program by more than one user at time or for serving more than one request by a single user. Each user request is kept track of as a thread with a separate identity. At any given time multiple requests may be kept in a queue. While processing a particular thread, the resource processing the thread may have to wait for completion of certain events (e.g. processing of an I/O operation such as reading and writing to a printer). During such waiting periods, multithreading capability allows the operating system to switch from processing one thread to another thread that is ready for processing (this is also known as thread context switching). Thus, the operating system can more efficiently manage the use of system resources. But interactions between threads can significantly complicate the software development process.
Although an operating system can allow concurrent use of a particular resource by two different threads, sometimes such concurrent uses can lead to errors referred to as race conditions. For example, if two threads of a multithreaded process are allowed to access a memory location and at least one of the accesses is for a write operation, a race condition is created because the result of the operation depends upon which thread executes the memory access first. Race conditions can cause serious errors in programs such as, security violations, data corruption and crashes.
Several programming techniques are used to manage the use of multiple threads (e.g. using, locks, mutexs, critical sections, event objects etc.). These are also commonly referred to as synchronization techniques. Even with the use of such techniques, race conditions may continue to occur due to errors in implementing these tools such as, missing or incorrect use of synchronization objects.
Furthermore, errors that can lead to race conditions are notoriously difficult to detect during a normal testing period. Although race conditions are more likely to occur due to thread context switches, such switches do not occur often enough to cause race condition errors during a normal testing period. Thus, the mean-time-to-failure of a multithreaded program due to a race condition between threads is particularly long. This means that a program can be tested a large number of times without a race condition ever occurring during the testing process. However, the bug may occur once the program is released to the market.
Thus, there is a need for a software testing tool that allows a developer to deliberately switch threads to cause race condition errors within a normal testing period, and is easily adaptable to be used with any given test case.